﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using HtmlAgilityPack;
using System.Text.RegularExpressions;

namespace Mvc.RazorTools.Glyphicons.CodeDesigner
{
	class Program
	{
		static void Main(string[] args)
		{
			Program.Process();
		}

		public static void Process()
		{
			// ***
			// *** Read the code template
			// ***
			string definitionsTemplate = Properties.Resources.CodeTemplate;
			string unitTestTemplate = Properties.Resources.UnitTestTemplate;
			string unitTestClassTemplate = Properties.Resources.UnitTestClassTemplate;

			// ***
			// *** The icons are read from the PNG folders and loaded into
			// *** an array that will then be used to generate the code.
			// ***
			var folders = new[]
			{
				new { Prefix = "glyphicons", Set = "Free", FolderPath = @"..\..\..\..\..\Assets\glyphicons_pro\glyphicons\png"},
				new { Prefix = "glyphicons_filetypes", Set = "FileTypes", FolderPath = @"..\..\..\..\..\\Assets\glyphicons_pro\glyphicons_filetypes\png"},
				new { Prefix = "glyphicons_halflings", Set = "Halflings", FolderPath = @"..\..\..\..\..\\Assets\glyphicons_pro\glyphicons_halflings\png"},
				new { Prefix = "glyphicons_social", Set = "Social", FolderPath = @"..\..\..\..\..\Assets\glyphicons_pro\glyphicons_social\png"},
			};

			// ***
			// *** Build a list of icons
			// ***
			List<Icon> icons = new List<Icon>();

			// ***
			// *** Load each folder...
			// ***
			foreach (var item in folders)
			{
				DirectoryInfo dir = new DirectoryInfo(item.FolderPath);

				// ***
				// *** Select all files ignoring the 2x versions
				// ***
				var files = (from tbl in dir.EnumerateFiles()
							 where !tbl.Name.Contains("2x")
							 select tbl).ToList();

				foreach (var file in files)
				{
					// ***
					// *** Parse the file name
					// ***
					string pattern = "^" + item.Prefix + @"_(?<code>\d{2,3})_(?<name>[a-zA-Z_]+)";
					Regex regex = new Regex(pattern);
					Match match = regex.Match(Path.GetFileNameWithoutExtension(file.Name));

					if (match.Success)
					{
						string name = ConvertName(match.Groups["name"].Value);

						var qry = from tbl in icons
								  where tbl.Name == name && tbl.Category == item.Set
								  select tbl;

						int index = qry.Count() + 1;

						icons.Add(new Icon()
						{
							Parent = icons,
							Index = index,
							Category = item.Set,
							Code = Convert.ToInt32(match.Groups["code"].Value),
							Name = name,
							Id = match.Groups["name"].Value
						});
					}
				}
			}


			// ***
			// *** Build the Initialization List
			// ***
			StringBuilder predefinedListSection = new StringBuilder();
			StringBuilder predefinedList = new StringBuilder();
			StringBuilder initList = new StringBuilder();
			StringBuilder unitTests = new StringBuilder();

			foreach (var item in folders)
			{
				predefinedListSection.Clear();
				var filteredIcons = icons.Where(t => t.Category == item.Set).OrderBy(t => t.Key).ToList();

				foreach (var icon in filteredIcons)
				{
					initList.AppendLine(string.Format("\t\t\t\t\t_allItems.Add(\"{0}\", Glyphicon.Create(\"{1}\", \"{2}\", \"{3}\", true));", icon.Key, icon.Category, icon.Id, icon.CodeName));

					predefinedListSection.AppendLine("\t\t\t/// <summary>");
					predefinedListSection.AppendLine(string.Format("\t\t\t/// Class = {0}", icon.Id));
					predefinedListSection.AppendLine("\t\t\t/// </summary>");
					predefinedListSection.AppendLine(string.Format("\t\t\tpublic static Glyphicon {0} = GlyphiconsSet.AllItems[\"{1}\"];", icon.CodeName, icon.Key));
					predefinedListSection.AppendLine(string.Empty);

					string unitTest = unitTestTemplate.Replace("%Category%", icon.Category);
					unitTest = unitTest.Replace("%_Name_%", icon.CodeName);
					unitTest = unitTest.Replace("%_Id_%", icon.Id);
					unitTests.AppendLine(unitTest);
					unitTests.AppendLine(string.Empty);
				}

				predefinedList.AppendLine(Properties.Resources.PredefinedListSection.Replace("%_IconSetName_%", item.Set).Replace("%_Predefined_List_%", predefinedListSection.ToString()));
				predefinedList.AppendLine();
			}

			// ***
			// *** Add the count to the template by replacing the
			// *** %_Icon_Count_% text
			// ***
			definitionsTemplate = definitionsTemplate.Replace("%_Icon_Count_%", icons.Count().ToString());

			// ***
			// *** Add the list to the template by replacing the
			// *** %_Init_List_% text
			// ***
			definitionsTemplate = definitionsTemplate.Replace("%_Init_List_%", initList.ToString());

			// ***
			// *** Add the list to the template by replacing the
			// *** %_Predefined_List_% text
			// ***
			definitionsTemplate = definitionsTemplate.Replace("%_Predefined_List_%", predefinedList.ToString());

			// ***
			// *** Add the list to the template by replacing the
			// *** %_Tests_% text
			// ***
			unitTestClassTemplate = unitTestClassTemplate.Replace("%_Tests_%", unitTests.ToString());

			// ***
			// *** Write the output files
			// ***
			File.WriteAllText("GlyphiconsSet.cs", definitionsTemplate);
			File.WriteAllText("PredefinedGlyphiconsTests.cs", unitTestClassTemplate);
		}

		public static string ConvertName(string value)
		{
			string returnValue = string.Empty;

			CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
			TextInfo textInfo = cultureInfo.TextInfo;
			returnValue = textInfo.ToTitleCase(value.Replace("_", " ")).Replace(" ", string.Empty);

			return returnValue;
		}
	}
}
